package com.gengzp.permission.interceptor;

import com.gengzp.permission.core.PermissionCoreFunc;
import com.gengzp.permission.core.PermissionVerificationProcessor;
import com.gengzp.permission.exception.PermissionException;
import com.gengzp.permission.model.UserPrincipalModel;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * @ClassName PermissionInterceptor
 * @Description 权限校验拦截器
 * @Author gengzp
 * @Date 2025/5/12 23:31
 */
@Component
public class PermissionInterceptor implements HandlerInterceptor, Ordered {

    @Autowired
    private PermissionVerificationProcessor permissionVerificationProcessor;

    @Autowired
    private PermissionCoreFunc permissionCoreFunc;

    /**
     * 请求执行前的拦截逻辑
     */
    @Override
    @SuppressWarnings("NullableProblems")
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws PermissionException {
        // 1.校验当前接口是否无需权限校验
        if (permissionVerificationProcessor
                .verifyRequestUriIsPermissionExempt(request.getRequestURI())) {
            return true;
        }

        // 2.校验当前接口是否使用了免登录注解 @AuthIgnore
        if (permissionVerificationProcessor
                .verifyRequestMethodHasAuthIgnoreAnnotation(handler)) {
            return true;
        }

        // 3.解析并校验用户认证信息
        UserPrincipalModel userPrincipalModel = permissionVerificationProcessor
                .parseAndVerifyRequestAuthentication(request, handler);

        // 4.若token解析认证通过, 则刷新缓存中的token过期时间, 并保存到当前线程变量中
        if (userPrincipalModel != null) {
            permissionCoreFunc.saveUserPrincipalModelToCache(userPrincipalModel);
            permissionCoreFunc.saveUserPrincipalModelThreadLocal(userPrincipalModel);
        }

        // 5.校验全部满足, 放行
        return true;
    }

    @Override
    @SuppressWarnings("NullableProblems")
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler, @Nullable Exception ex) {
        // 清空线程变量中的用户登录状态信息
        permissionCoreFunc.clearUserPrincipalModelThreadLocal();
    }

    /**
     * 权限校验框架优先级定义
     */
    @Override
    public int getOrder() {
        // 权限验证的拦截器优先级最高, 因此使用最小的Integer
        return Ordered.HIGHEST_PRECEDENCE;
    }

}
